1 /*
2 * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 4984407 5033578
27 * @summary Tests for {Math, StrictMath}.pow
28 * @author Joseph D. Darcy
29 */
30
31 public class PowTests {
32 private PowTests(){}
33
34 static final double infinityD = Double.POSITIVE_INFINITY;
35
36 static int testPowCase(double input1, double input2, double expected) {
37 int failures = 0;
38 failures += Tests.test("StrictMath.pow(double, double)", input1, input2,
39 StrictMath.pow(input1, input2), expected);
40 failures += Tests.test("Math.pow(double, double)", input1, input2,
41 Math.pow(input1, input2), expected);
42 return failures;
43 }
44
45
46 static int testStrictPowCase(double input1, double input2, double expected) {
47 int failures = 0;
48 failures += Tests.test("StrictMath.pow(double, double)", input1, input2,
49 StrictMath.pow(input1, input2), expected);
50 return failures;
51 }
52
53 static int testNonstrictPowCase(double input1, double input2, double expected) {
54 int failures = 0;
55 failures += Tests.test("Math.pow(double, double)", input1, input2,
56 Math.pow(input1, input2), expected);
57 return failures;
58 }
59
60 /*
61 * Test for bad negation implementation.
62 */
63 static int testPow() {
64 int failures = 0;
65
66 double [][] testCases = {
67 {-0.0, 3.0, -0.0},
68 {-0.0, 4.0, 0.0},
69 {-infinityD, -3.0, -0.0},
70 {-infinityD, -4.0, 0.0},
71 };
72
73 for (double[] testCase : testCases) {
74 failures+=testPowCase(testCase[0], testCase[1], testCase[2]);
75 }
76
77 return failures;
78 }
79
80 /*
81 * Test cross-product of different kinds of arguments.
82 */
83 static int testCrossProduct() {
84 int failures = 0;
85
86 double testData[] = {
87 Double.NEGATIVE_INFINITY,
88 /* > -oo */ -Double.MAX_VALUE,
89 /**/ (double)Long.MIN_VALUE,
90 /**/ (double) -((1L<<53)+2L),
91 /**/ (double) -((1L<<53)),
92 /**/ (double) -((1L<<53)-1L),
93 /**/ -((double)Integer.MAX_VALUE + 4.0),
94 /**/ (double)Integer.MIN_VALUE - 1.0,
95 /**/ (double)Integer.MIN_VALUE,
96 /**/ (double)Integer.MIN_VALUE + 1.0,
97 /**/ -Math.PI,
98 /**/ -3.0,
99 /**/ -Math.E,
100 /**/ -2.0,
101 /**/ -1.0000000000000004,
102 /* < -1.0 */ -1.0000000000000002, // nextAfter(-1.0, -oo)
103 -1.0,
104 /* > -1.0 */ -0.9999999999999999, // nextAfter(-1.0, +oo)
105 /* > -1.0 */ -0.9999999999999998,
106 /**/ -0.5,
107 /**/ -1.0/3.0,
108 /* < 0.0 */ -Double.MIN_VALUE,
109 -0.0,
110 +0.0,
111 /* > 0.0 */ +Double.MIN_VALUE,
112 /**/ +1.0/3.0,
113 /**/ +0.5,
114 /**/ +0.9999999999999998,
115 /* < +1.0 */ +0.9999999999999999, // nextAfter(-1.0, +oo)
116 +1.0,
117 /* > 1.0 */ +1.0000000000000002, // nextAfter(+1.0, +oo)
118 /**/ +1.0000000000000004,
119 /**/ +2.0,
120 /**/ +Math.E,
121 /**/ +3.0,
122 /**/ +Math.PI,
123 /**/ -(double)Integer.MIN_VALUE - 1.0,
124 /**/ -(double)Integer.MIN_VALUE,
125 /**/ -(double)Integer.MIN_VALUE + 1.0,
126 /**/ (double)Integer.MAX_VALUE + 4.0,
127 /**/ (double) ((1L<<53)-1L),
128 /**/ (double) ((1L<<53)),
129 /**/ (double) ((1L<<53)+2L),
130 /**/ -(double)Long.MIN_VALUE,
131 /* < oo */ Double.MAX_VALUE,
132 Double.POSITIVE_INFINITY,
133 Double.NaN
134 };
135
136 double NaN = Double.NaN;
137 for(double x: testData) {
138 for(double y: testData) {
139 boolean testPass = false;
140 double expected=NaN;
141 double actual;
142
143 // First, switch on y
144 if( Double.isNaN(y)) {
145 expected = NaN;
146 } else if (y == 0.0) {
147 expected = 1.0;
148 } else if (Double.isInfinite(y) ) {
149 if(y > 0) { // x ^ (+oo)
150 if (Math.abs(x) > 1.0) {
151 expected = Double.POSITIVE_INFINITY;
152 } else if (Math.abs(x) == 1.0) {
153 expected = NaN;
154 } else if (Math.abs(x) < 1.0) {
155 expected = +0.0;
156 } else { // x is NaN
157 assert Double.isNaN(x);
158 expected = NaN;
159 }
160 } else { // x ^ (-oo)
161 if (Math.abs(x) > 1.0) {
162 expected = +0.0;
163 } else if (Math.abs(x) == 1.0) {
164 expected = NaN;
165 } else if (Math.abs(x) < 1.0) {
166 expected = Double.POSITIVE_INFINITY;
167 } else { // x is NaN
168 assert Double.isNaN(x);
169 expected = NaN;
170 }
171 } /* end Double.isInfinite(y) */
172 } else if (y == 1.0) {
173 expected = x;
174 } else if (Double.isNaN(x)) { // Now start switching on x
175 assert y != 0.0;
176 expected = NaN;
177 } else if (x == Double.NEGATIVE_INFINITY) {
178 expected = (y < 0.0) ? f2(y) :f1(y);
179 } else if (x == Double.POSITIVE_INFINITY) {
180 expected = (y < 0.0) ? +0.0 : Double.POSITIVE_INFINITY;
181 } else if (equivalent(x, +0.0)) {
182 assert y != 0.0;
183 expected = (y < 0.0) ? Double.POSITIVE_INFINITY: +0.0;
184 } else if (equivalent(x, -0.0)) {
185 assert y != 0.0;
186 expected = (y < 0.0) ? f1(y): f2(y);
187 } else if( x < 0.0) {
188 assert y != 0.0;
189 failures += testStrictPowCase(x, y, f3(x, y));
190 failures += testNonstrictPowCase(x, y, f3ns(x, y));
191 continue;
192 } else {
193 // go to next iteration
194 expected = NaN;
195 continue;
196 }
197
198 failures += testPowCase(x, y, expected);
199 } // y
200 } // x
201 return failures;
202 }
203
204 static boolean equivalent(double a, double b) {
205 return Double.compare(a, b) == 0;
206 }
207
208 static double f1(double y) {
209 return (intClassify(y) == 1)?
210 Double.NEGATIVE_INFINITY:
211 Double.POSITIVE_INFINITY;
212 }
213
214
215 static double f2(double y) {
216 return (intClassify(y) == 1)?-0.0:0.0;
217 }
218
219 static double f3(double x, double y) {
220 switch( intClassify(y) ) {
221 case 0:
222 return StrictMath.pow(Math.abs(x), y);
223 // break;
224
225 case 1:
226 return -StrictMath.pow(Math.abs(x), y);
227 // break;
228
229 case -1:
230 return Double.NaN;
231 // break;
232
233 default:
234 throw new AssertionError("Bad classification.");
235 // break;
236 }
237 }
238
239 static double f3ns(double x, double y) {
240 switch( intClassify(y) ) {
241 case 0:
242 return Math.pow(Math.abs(x), y);
243 // break;
244
245 case 1:
246 return -Math.pow(Math.abs(x), y);
247 // break;
248
249 case -1:
250 return Double.NaN;
251 // break;
252
253 default:
254 throw new AssertionError("Bad classification.");
255 // break;
256 }
257 }
258
259 static boolean isFinite(double a) {
260 return (0.0*a == 0);
261 }
262
263 /**
264 * Return classification of argument: -1 for non-integers, 0 for
265 * even integers, 1 for odd integers.
266 */
267 static int intClassify(double a) {
268 if(!isFinite(a) || // NaNs and infinities
269 (a != Math.floor(a) )) { // only integers are fixed-points of floor
270 return -1;
271 }
272 else {
273 // Determine if argument is an odd or even integer.
274
275 a = StrictMath.abs(a); // absolute value doesn't affect odd/even
276
277 if(a+1.0 == a) { // a > maximum odd floating-point integer
278 return 0; // Large integers are all even
279 }
280 else { // Convert double -> long and look at low-order bit
281 long ell = (long) a;
282 return ((ell & 0x1L) == (long)1)?1:0;
283 }
284 }
285 }
286
287 public static void main(String [] argv) {
288 int failures = 0;
289
290 failures += testPow();
291 failures += testCrossProduct();
292
293 if (failures > 0) {
294 System.err.println("Testing pow incurred "
295 + failures + " failures.");
296 throw new RuntimeException();
297 }
298 }
299 }